package controllers

import command.CommandExec
import dao._
import play.api.mvc.{AbstractController, ControllerComponents}
import tool.{FormTool, Tool}
import upickle.default.writeJs

import java.io.File
import javax.inject.Inject
import implicits.Implicits._
import play.utils.UriEncoding
import tool.Pojo.CommandData

import scala.concurrent.ExecutionContext.Implicits.global
import upickle.default._
import ujson.play.PlayJson

import java.nio.charset.Charset
import java.nio.file.Files

/** Created by yz on 11/5/2022
  */
class ToolController @Inject() (cc: ControllerComponents)(implicit
    val modeDao: ModeDao
) extends AbstractController(cc) {

  import shared.tsPojo.TsPojo.tool._

  def getFileColumn = Action { implicit request =>
    val data = FormTool.columnNameForm.bindFromRequest().get
    val fileName = FormTool.fileNameForm.bindFromRequest().get.fileName
    val file = new File(Tool.dataDir, fileName)
    val array = file.txtLines
      .map(_.trimQuote)
      .lineSeqMap
      .map { map =>
        map(data.columnName)
      }
      .distinct
      .sorted
    Ok(writeJs(array))
  }

  def downloadFile = Action { implicit request =>
    val fileName = FormTool.fileNameForm.bindFromRequest().get.fileName
    val file = new File(Tool.dataDir, fileName)
    Ok.sendFile(file)
      .withHeaders(
        CONTENT_DISPOSITION -> ("attachment; filename=" + file.getName),
        CONTENT_TYPE -> "application/x-download"
      )
  }
  def pathDownloadFile(fileName: String) = Action { implicit request =>
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.dataDir, trueFileName)
    Ok.sendFile(file)
      .withHeaders(
        CONTENT_DISPOSITION -> ("attachment; filename=" + file.getName),
        CONTENT_TYPE -> "application/x-download"
      )
  }
  def png2jpeg = Action { implicit request =>
    val data = PlayJson.transform(request.body.asJson.get, reader[Png2jpeg.Request])
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val inputFile = new File(tmpDir, "input.png")
    data.base64.base642pngFile(inputFile)
    val outFile = new File(tmpDir, "out.jpg")
    val command =
      s"""
           |convert ${inputFile.unixPath}  ${outFile.unixPath}
           |""".stripMargin
    val commandExec = CommandExec().exec { b =>
      CommandData(tmpDir, command)
    }

    val response = if (commandExec.isSuccess) {
      Png2jpeg.Response(valid = true, base64 = outFile.base64)
    } else {
      Png2jpeg.Response(valid = false, message = commandExec.errorInfo)
    }
    Tool.deleteDirectory(tmpDir)
    Ok(writeJs(response))
  }

  def png2pdf = Action { implicit request =>
    val startTime = System.currentTimeMillis()
    val data = PlayJson.transform(request.body.asJson.get, reader[Png2jpeg.Request])
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val inputFile = new File(tmpDir, "input.png")
    val outFile = new File(tmpDir, "out.pdf")
    data.base64.base642pngFile(inputFile)
    val command =
      s"""
           |convert ${inputFile.unixPath}  ${outFile.unixPath}
           |""".stripMargin
    val commandExec = CommandExec().exec { b =>
      CommandData(tmpDir, command)
    }

    val response = if (commandExec.isSuccess) {
      Png2jpeg.Response(valid = true, base64 = outFile.base64)
    } else {
      Png2jpeg.Response(valid = false, message = commandExec.errorInfo)
    }
    Tool.deleteDirectory(tmpDir)
    Ok(writeJs(response))
  }

  def png2svg = Action { implicit request =>
    val data = PlayJson.transform(request.body.asJson.get, reader[Png2jpeg.Request])
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val inputFile = new File(tmpDir, "input.png")
    data.base64.base642pngFile(inputFile)
    val outFile = new File(tmpDir, "out.svg")
    val command =
      s"""
           |convert ${inputFile.unixPath}  ${outFile.unixPath}
           |""".stripMargin

    val commandExec = CommandExec().exec { b =>
      CommandData(tmpDir, command)
    }

    val response = if (commandExec.isSuccess) {
      Png2jpeg.Response(valid = true, base64 = outFile.base64)
    } else {
      Png2jpeg.Response(valid = false, message = commandExec.errorInfo)
    }
    Tool.deleteDirectory(tmpDir)
    Ok(writeJs(response))
  }

  def featurePlot(fileName: String) = Action { implicit request =>
    val ifModifiedSinceStr = request.headers.get(IF_MODIFIED_SINCE)
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.featurePlotDir, trueFileName)
    val lastModifiedStr = file.lastModified().toString
    val MimeType = "image/png"
    val byteArray = Files.readAllBytes(file.toPath)
    if (ifModifiedSinceStr.isDefined && ifModifiedSinceStr.get == lastModifiedStr) {
      NotModified
    } else {
      Ok(byteArray).as(MimeType).withHeaders(LAST_MODIFIED -> file.lastModified().toString)
    }
  }
  def pngImage(fileName: String) = Action { implicit request =>
    val ifModifiedSinceStr = request.headers.get(IF_MODIFIED_SINCE)
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.dataDir, trueFileName)
    val lastModifiedStr = file.lastModified().toString
    val MimeType = "image/png"
    val byteArray = Files.readAllBytes(file.toPath)
    if (ifModifiedSinceStr.isDefined && ifModifiedSinceStr.get == lastModifiedStr) {
      NotModified
    } else {
      Ok(byteArray).as(MimeType).withHeaders(LAST_MODIFIED -> file.lastModified().toString)
    }
  }
  def featurePlotDownload(fileName: String) = Action { implicit request =>
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.featurePlotDir, trueFileName)
    Ok.sendFile(file)
      .withHeaders(
        CONTENT_DISPOSITION -> ("attachment; filename=" + file.getName),
        CONTENT_TYPE -> "application/x-download"
      )
  }

  def dimPlot(fileName: String) = Action { implicit request =>
    val ifModifiedSinceStr = request.headers.get(IF_MODIFIED_SINCE)
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.dimPlotDir, trueFileName)
    val lastModifiedStr = file.lastModified().toString
    val MimeType = "image/png"
    val byteArray = Files.readAllBytes(file.toPath)
    if (ifModifiedSinceStr.isDefined && ifModifiedSinceStr.get == lastModifiedStr) {
      NotModified
    } else {
      Ok(byteArray).as(MimeType).withHeaders(LAST_MODIFIED -> file.lastModified().toString)
    }
  }

  def dimPlotDownload(fileName: String) = Action { implicit request =>
    val trueFileName = UriEncoding.decodePath(fileName, "UTF-8")
    val file = new File(Tool.dimPlotDir, trueFileName)
    Ok.sendFile(file)
      .withHeaders(
        CONTENT_DISPOSITION -> ("attachment; filename=" + file.getName),
        CONTENT_TYPE -> "application/x-download"
      )
  }

  def outImages(fileName: String) = Action { implicit request =>
    val ifModifiedSinceStr = request.headers.get(IF_MODIFIED_SINCE)
    val file = new File(Tool.imagesDir, fileName)
    val lastModifiedStr = file.lastModified().toString
    val MimeType = "image/png"
    val byteArray = Files.readAllBytes(file.toPath)
    if (ifModifiedSinceStr.isDefined && ifModifiedSinceStr.get == lastModifiedStr) {
      NotModified
    } else {
      Ok(byteArray).as(MimeType).withHeaders(LAST_MODIFIED -> file.lastModified().toString)
    }
  }

  def outImagesDownload(fileName: String) = Action { implicit request =>
    val file = new File(Tool.imagesDir, fileName)
    Ok.sendFile(file)
      .withHeaders(
        CONTENT_DISPOSITION -> ("attachment; filename=" + file.getName),
        CONTENT_TYPE -> "application/x-download"
      )
  }

}
